5. Implementación del método de Bairstow para el cálculo de raíces reales y complejas apartir de un polinomio dado


In [ ]:
#!/usr/local/bin/python
# coding: utf-8

import math
import cmath
import numpy as np
import sys

def cuadratica(r,s): #hallar 2 raices en grados mayores a 2
    discrim = math.pow(r,2)+(4*s)
    raices = []
    if discrim > 0: #raiz real
        raices.append((r+math.sqrt(discrim))/(2))
        raices.append((r-math.sqrt(discrim))/(2))
    else: #raiz compleja
        raices.append((r-cmath.sqrt(discrim))/2)
        raices.append((r+cmath.sqrt(discrim))/2)
    return raices

def cuadratica2(a,b,c): #hallar últimas 2 raices
    discrim = math.pow(b,2)-(4*a*c)
    raices = []
    if discrim > 0: #raiz real
        raices.append((-b+math.sqrt(discrim))/(2*a))
        raices.append((-b-math.sqrt(discrim))/(2*a))
    else: #raiz compleja
        raices.append((-b-cmath.sqrt(discrim))/(2*a))
        raices.append((-b+cmath.sqrt(discrim))/(2*a))
    return raices

def generateb(a, r, s): #implementacion de relación de concurrencia para hallar residuos de división sintética
    b = []
    b.append(a[0])
    b.append(a[1]+(r*b[-1]))
    for i in a[2:]:
        b.append(i+(r*b[-1])+(s*b[-2]))
    return b

def generatec(b, r, s): #implementacion de relación de concurrencia para hallar derivadas parciales
    c = []
    c.append(b[0])
    c.append(b[1]+(r*c[-1]))
    for i in b[2:-1]:
        c.append(i+(r*c[-1])+(s*c[-2]))
    return c

def bairstow(r,s,a,errorA):
    grado = len(a)-1
    noIter = 1
    listaRaices = []
    b = []
    while grado > 0:
        noIter=0
        rerror = 100
        serror = 100
        if grado == 1:
            print('**********************************************')
            print('Hallando última raíz')
            print('**********************************************')
            if len(b) != 0:
                listaRaices.append(-b[1]/b[0])
            else:
                listaRaices.extend(cuadratica2(a[0],a[1],a[2]))
            grado -= 1
        elif grado == 2:
            print('**********************************************')
            print('Hallando las dos últimas raíces')
            print('**********************************************')
            if len(b) != 0:
                listaRaices.extend(cuadratica2(b[0],b[1],b[2]))
            else:
                listaRaices.extend(cuadratica2(a[0],a[1],a[2]))
            grado -= 2
        else:
            print('**********************************************')
            print('Hallando 2 raices')
            while rerror>errorA or serror>errorA:
                b = generateb(a,r,s) #b4, b3, b2, b1, b0 ...
                c = generatec(b,r,s) #c4, c3, c2, c1
                eq1 = np.array([[c[-2],c[-3]],[c[-1],c[-2]]])
                eq2 = np.array([-b[-2],-b[-1]])
                solEq = np.linalg.solve(eq1,eq2) #resolver sistema de ecuaciones usando matrices
                rdelta = solEq[0]
                sdelta = solEq[1]
                r += rdelta
                s += sdelta
                rerror = abs(rdelta/r)*100 #calcula errores relativos de r y s
                serror = abs(sdelta/s)*100
                noIter+=1
            print('Error de r:',str(rerror))
            print('Error de s:',str(serror))
            print('No. iter realizadas:',str(noIter))
            print('**********************************************')
            listaRaices.extend(cuadratica(r,s))
            a = b[:-2]
            grado -= 2
    return listaRaices

def main(argv):
    print('----------------------------------------------')
    print('Universidad Distrital Francisco José de Caldas')
    print('Análisis y métodos numéricos')
    print('Ejercicio 5 - Parcial I')
    print('Método de Bairstow')
    print('----------------------------------------------')
    r = float(input('A continuación ingrese un valor para R: '))
    s = float(input('Ingrese un valor para S: '))
    errorA = float(input('Ingrese el número de dígitos de precisión: '))
    grado = int(input('Ingrese el grado del polinomio al cual desea calcularle las raices: '))
    a = []
    print('A continuación por favor ingrese los coeficientes de los términos del polinomio de mayor a menor grado:')
    coef = range(0,grado+1)
    coef.reverse()
    for i in coef:
        a.append(float(input('Coeficiente x'+str(i)+': ')))
    print("\n\n----------------------------------------------")
    print('---------------Calculando---------------------')
    print("----------------------------------------------\n")
    cont = 1
    raices = bairstow(r,s,a,math.pow(10,-errorA))
    print("\n")
    print("\n----------------------------------------------")
    print('---------------Resultados---------------------')
    print("----------------------------------------------\n")
    for i in raices:
        print('Raíz no.'+str(cont)+' : '+str(i))
        cont += 1
    print("Polinomio factorizado:")
    pol = ""
    for i in raices:
        if 'j' in str(i): #raíz compleja
            pol+="(x+"+str(-i)+")"
        else:
            pol+="(x+("+str(-i)+"))"
    print(pol)
        
if __name__ == "__main__":
    main(sys.argv)

Output - ejecución del programa con el polinomio de grado 5 "x^5 -3.5x^4 + 2.75x^3 + 2.125x^2 - 3.875x + 1.25" con r=0, s=0, número de dígitos de precisión=4


In [ ]:
yair@yair-915S3G ~/D/n/finding roots> python parcial.py 
----------------------------------------------
Universidad Distrital Francisco José de Caldas
Análisis y métodos numéricos
Ejercicio 5 - Parcial I
Método de Bairstow
A continuación ingrese un valor para R: 0
Ingrese un valor para S: 0
Ingrese el número de dígitos de precisión: 4
Ingrese el grado del polinomio al cual desea calcularle las raices: 5
A continuación por favor ingrese los coeficientes de los términos del polinomio de mayor a menor grado:
Coeficiente x5: 1
Coeficiente x4: -3.5
Coeficiente x3: 2.75
Coeficiente x2: 2.125
Coeficiente x1: -3.875
Coeficiente x0: 1.25
---------------Calculando---------------------
Hallando 2 raices
('Error de r:', '4.77627291373e-10')
('Error de s:', '2.1809470714e-10')
('No. iter realizadas:', '9')
Hallando 2 raices
('Error de r:', '3.91187303182e-06')
('Error de s:', '3.60322877302e-06')
('No. iter realizadas:', '22')
Hallando última raíz
---------------Resultados---------------------
Raíz no.1 : 2.0
Raíz no.2 : -1.0
Raíz no.3 : (1-0.500000000011j)
Raíz no.4 : (1+0.500000000011j)
Raíz no.5 : 0.49999992175
Polinomio factorizado:
(x+(-2.0))(x+(1.0))(x+(-1+0.500000000011j))(x+(-1-0.500000000011j))(x+(-0.49999992175))